/**
 *
 */
package de.guidoludwig.af;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.SwingWorker;

import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.beans.DelayedPropertyChangeHandler;
import com.jgoodies.binding.list.SelectionInList;
import com.jgoodies.binding.value.ValueModel;

import de.guidoludwig.jtm.SearchModel;
import de.guidoludwig.jtm.domain.AbstractPersistentObject;
import de.guidoludwig.jtm.server.AbstractRepository;

/**
 * @author guido
 *
 */
public abstract class AbstractHomeModel<T extends AbstractPersistentObject> {

	private final SearchModel searchModel;
	private final SelectionInList<T> searchResultList;
	private final BeanAdapter<SearchModel> searchModelAdapter;
	private final BeanAdapter<T> selectionAdapter;
	private SearchWorker searchWorker;

	protected AbstractHomeModel() {
		searchModel = new SearchModel();
		searchResultList = new SelectionInList<T>();
		searchModelAdapter = new BeanAdapter<SearchModel>(searchModel);
		DelayedPropertyChangeHandler criteriaListener = new DelayedPropertyChangeHandler(
				300) {
			@Override
			public void delayedPropertyChange(PropertyChangeEvent arg0) {
				search();
			}
		};
		searchModel.addPropertyChangeListener(SearchModel.PROPERTY_CRITERIA,
				criteriaListener);
		selectionAdapter = new BeanAdapter<T>((T) null);
		searchResultList.addPropertyChangeListener(
				SelectionInList.PROPERTYNAME_SELECTION,
				new PropertyChangeListener() {
					@Override
					public void propertyChange(PropertyChangeEvent evt) {
						selectionAdapter.setBean(searchResultList
								.getSelection());
					}
				});
	}

	protected abstract AbstractRepository<T> getRepository() throws Exception;

	public final ValueModel getCriteriaModel() {
		return searchModelAdapter.getValueModel(SearchModel.PROPERTY_CRITERIA);
	}

	public final void search() {
		if (searchWorker != null && !searchWorker.isDone()) {
			searchWorker.cancel(true);
		}
		searchWorker = new SearchWorker();
		searchWorker.execute();
	}

	public final SearchModel getSearchModel() {
		return searchModel;
	}

	public final SelectionInList<T> getSearchResultList() {
		return searchResultList;
	}

	public final BeanAdapter<T> getSelectionAdapter() {
		return selectionAdapter;
	}


	private final class SearchWorker extends SwingWorker<List<T>, Void> {

		List<T> result;

		private SearchWorker() {
			result = null;
		}

		@Override
		protected List<T> doInBackground() throws Exception {
			AbstractRepository<T> repo;
			try {
				repo = getRepository();
				result = repo.findIntelli(searchModel);
				return result;
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}


		@Override
		protected void done() {
			if (!isCancelled()) {
				searchResultList.setList(result);
			}
		}

	}
}
